package com.itcast.util;

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * elasticsearch 查询工具类
 *
 * @Author JinX
 * @Date 1/15/2021 11:01 AM
 * @Version 1.0
 */
public class EscUtil {

    private final static RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
            //如果是集群，则设置多个主机，注意端口是http协议的端口
            new HttpHost("localhost", 9200)
    ));

    private EscUtil() {
    }

    /**
     * 根据传入的查询构造器执行查询
     *
     * @param builder
     * @param index
     * @return SearchResponse
     */
    public static SearchResponse query(SearchSourceBuilder builder, String... index) {
        SearchRequest searchRequest = new SearchRequest(index);
        searchRequest.source(builder);
        SearchResponse response = null;

        try {
            response = client.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return response;
    }

    /**
     * 返回一个集合
     *
     * @param builder
     * @param clazz
     * @param index
     * @param <T>
     * @return
     */
    public static <T> List<T> query(SearchSourceBuilder builder, Class clazz, String... index) {
        SearchResponse response = query(builder, index);
        SearchHits hits = response.getHits();
        ArrayList<T> list = new ArrayList<>();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            T t = JSON.parseObject(sourceAsString, (Type) clazz);
            list.add(t);
        }
        return list;
    }

    /**
     * 高亮显示查询结果
     *
     * @param builder 查询条件构造器
     * @param clazz   返回列表中的类型
     * @param filed   需要高亮显示的字段
     * @param index   需要查询的索引库名称
     * @param <T>
     * @return
     */
    public static <T> List<T> highlightQuery(SearchSourceBuilder builder, Class clazz, String filed, String... index) {
        builder.highlighter(new HighlightBuilder().field(filed).preTags("<span style=\"color: red\">").postTags("</span>"));

        SearchResponse response = query(builder, index);
        SearchHits hits = response.getHits();
        ArrayList<T> list = new ArrayList<>();
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            T t = JSON.parseObject(sourceAsString, (Type) clazz);

            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (highlightFields != null && highlightFields.size() != 0) {
                HighlightField field = highlightFields.get(filed);
                Text[] fragments = field.getFragments();
                String res = StringUtils.join(fragments);
                try {
                    Method method = clazz.getDeclaredMethod("set" + StringUtils.capitalize(filed),
                            clazz.getDeclaredField(filed).getType());
                    method.invoke(t, res);
                    list.add(t);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return list;
    }

}
